package com.graphhopper.util.obstacle;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.graphhopper.util.FileToStringUtils;
import com.graphhopper.vo.ObstacleVo;

import java.io.File;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 建筑物定位选择
 *
 * @author Administrator
 */
public class BuildingSelect {

    public static ExecutorService executorService;

    private static final ObjectMapper objectMapper = new ObjectMapper();

    private static final TypeReference<List> typeReference = new TypeReference<List>() {
    };

    private static final int laminationNum = 8;
    private static final Map<Integer, List<ObstacleVo>> buildMap;

    private static int floorHeight = 3;
    static {
        buildMap = new HashMap<>(32);
        executorService = newFixedThreadPool(10);
        for (int i = 1; i <= laminationNum; i++) {
            buildMap.put(i, new ArrayList<>(1024));
        }
    }

    private static ExecutorService newFixedThreadPool(int nThreads) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        return executor;
    }

    public static Map<Integer, List<ObstacleVo>> buildMapALL() {
        return buildMap;
    }

    public static List<ObstacleVo> buildListALL() {
       return  new ArrayList(buildMap.values());
    }


    public static List<ObstacleVo> obstacleVo(int key) {
        return buildMap.get(key);
    }

    public static List<ObstacleVo> obstacleVoInterval(List<Integer> keys){
        List<ObstacleVo> list=new ArrayList<>(1024);
        keys.forEach(a->{
            List<ObstacleVo>  listTemp = obstacleVo(a);
            if(listTemp !=null){
                list.addAll(listTemp);
            }
        });
        return list;
    }

    public static void init(String buildUrl) {
        File geoZJ = new File(buildUrl);
        if (geoZJ == null || !geoZJ.exists()) {
            throw new IllegalArgumentException("建筑物数据不存在");
        }
        try {
            String json = FileToStringUtils.txt2String(geoZJ);
            List posList = objectMapper.readValue(json, typeReference);
            int row = posList.size();
            for (int i = 0; i < row; i++) {
                LinkedHashMap linkedHashMap = (LinkedHashMap) posList.get(i);
                Integer index = (Integer) linkedHashMap.get("index");
                ArrayList list = (ArrayList) linkedHashMap.get("data");
                obstacle(index, list);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void obstacle(Integer index, ArrayList list) {
        int listSize = list.size();
        for (int h = 0; h < listSize; h++) {
            LinkedHashMap data = (LinkedHashMap) list.get(h);
            ArrayList points = (ArrayList) data.get("coordinates");
            Integer floor = (Integer) data.get("Floor");
            coordinates(points, index, h, floor);
        }
    }

    private static void coordinates(ArrayList coordinates, Integer index, int h, Integer floor) {
        int pintSize = coordinates.size();
        for (int j = 0; j < pintSize; j++) {
            ArrayList dataPoints = (ArrayList) coordinates.get(j);
            int bilderMore = dataPoints.size();
            StringBuilder stringBuilder = new StringBuilder(1024);
            for (int m = 0; m < bilderMore; m++) {
                ArrayList dataPoint = (ArrayList) dataPoints.get(m);
                stringBuilder.append(dataPoint.get(0)).append(",").append(dataPoint.get(1)).append(";");
            }
            String dataInfo = stringBuilder.substring(0, stringBuilder.length() - 1);
            ObstacleVo obstacleVo = new ObstacleVo();
            obstacleVo.setHeight(floor * floorHeight);
            obstacleVo.setId(index + "_" + h + "_" + j);
            obstacleVo.setPoints(dataInfo);
            buildMap.get(index).add(obstacleVo);
        }
    }

}
